package cn.nzp.core.openapi.server.si.files;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.UUID;


import cn.nzp.core.common.utils.CoreUtils;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.StorageClass;
import com.qcloud.cos.region.Region;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


import cn.nzp.core.common.consts.CoreConsts;
import cn.nzp.core.common.exception.DataException;
import cn.nzp.core.common.file.FileTypeConsts;
import cn.nzp.core.common.file.MyFileUtils;
import cn.nzp.core.query.resp.RespConsts;
import cn.nzp.sag.mp.eoa.client.dto.EoaFilePropDto;

import javax.annotation.PostConstruct;

/**
 * @Author DELL
 * @Description
 * @Date 2021-08-12
 */
@Service
public class EoaCosFileHandler {

    private static final Logger LOG = LoggerFactory.getLogger(EoaCosFileHandler.class);

    private COSClient cosclient = null;

    @Value("tx.cos.bucketName")
    private String bucketName;
    @Value("tx.cos.regionName")
    private String regionName;
    @Value("tx.cos.accessKey")
    private String accessKey;
    @Value("tx.cos.secretKey")
    private String secretKey;

    private static final String JPG = "jpg";

    private static final String AMR = "amr";

    @PostConstruct
    public void init() {
        // 初始化用户身份信息(secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey);
        // 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(new Region(regionName));
        // 设置生成的 url 的协议名
        clientConfig.setHttpProtocol(HttpProtocol.http);
        // 生成cos客户端
        cosclient = new COSClient(cred, clientConfig);
    }

    public String getObjectUrl(String key) {

        return cosclient.getObjectUrl(bucketName, key).toString();
    }

    public EoaFilePropDto fetchFileProp(String url, String mediaid) {
        EoaFilePropDto filePropDto = new EoaFilePropDto();

        BufferedInputStream bfis = null;
        InputStream inputStream = null;
        try {
            URL fileURL = new URL(url);

            URLConnection conn = fileURL.openConnection();
            if (conn == null) {
                // url无法访问
                return null;
            }
            // -1 if the content length is not known, or if the content length is greater than Integer.MAX_VALUE.
            int contentLength = conn.getContentLength();
            String contentType = conn.getContentType();
            filePropDto.setFileSize(contentLength);
            inputStream = fileURL.openStream();

            String fileKey = simpleUploadFileFromStream(inputStream, contentType, contentLength, "common");
            String fileUrl = getObjectUrl(fileKey);

            String fileType = null;
            bfis = new BufferedInputStream(inputStream);
            bfis.mark(10); // 先标记（暂存）
            //获取文件头的前六位
            byte[] b = new byte[3];
            bfis.read(b, 0, b.length);
            String fileCode = MyFileUtils.bytesToHexString(b);
            Iterator<String> keyIter = FileTypeConsts.FILE_TYPE_MAP.keySet().iterator();
            while (keyIter.hasNext()) {
                String key = keyIter.next();
                //比较前几位是否相同就可以判断文件格式（相同格式文件文件头后面几位会有所变化）
                if (key.toLowerCase().startsWith(fileCode.toLowerCase()) || fileCode.toLowerCase().startsWith(key.toLowerCase())) {
                    fileType = FileTypeConsts.FILE_TYPE_MAP.get(key);
                    break;
                }
            }
            if (StringUtils.equalsIgnoreCase(contentType, "audio/amr")) {
                fileType = AMR;
            }
            if (StringUtils.isBlank(fileType)) {
                LOG.info("UnknowFileType -> content-type:[{}] ,contentLength:[{}], byMediaId:[{}]", contentType, contentLength, mediaid);
                fileType = JPG;
            }
            String fileName = mediaid.concat(CoreConsts.POINT).concat(fileType);

            filePropDto.setFileSize(contentLength);
            filePropDto.setFileType(fileType);
            filePropDto.setFileName(fileName);
            filePropDto.setFileUrl(fileUrl);

        } catch (Throwable e) {
            throw new DataException("腾讯cos上传文件错误", e);
        } finally {
            try {
                inputStream.close();
                bfis.close();
            } catch (IOException e) {
                LOG.error(e.getMessage(), e);
            }
        }


        return filePropDto;
    }

//    public static void main(String[] args) {
//        String key = "aaa/bbb.txt";
//        File localFile = new File("D://len10M.txt");
//        try {
//            InputStream input = new FileInputStream(localFile) ;
//            new EoaCosFileHandler().simpleUploadFileFromStream(input, "", localFile.length());
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//
//    }


    public String simpleUploadFileFromStream(InputStream input, String contentType, long contentLength, String bizType) throws IOException {

        if (CoreUtils.isEmpty(bizType)) {
            bizType = "common";
        }

        String key = bizType + "/" + UUID.randomUUID().toString();

        LOG.info("开始上传文件key: {} ", key);

        ObjectMetadata objectMetadata = new ObjectMetadata();
        // 从输入流上传必须制定content length, 否则http客户端可能会缓存所有数据，存在内存OOM的情况
        objectMetadata.setContentLength(contentLength);
        // 默认下载时根据cos路径key的后缀返回响应的contenttype, 上传时设置contenttype会覆盖默认值
        objectMetadata.setContentType(contentType);

        PutObjectRequest putObjectRequest =
                new PutObjectRequest(bucketName, key, input, objectMetadata);
        // 设置存储类型, 默认是标准(Standard), 低频(standard_ia)
        putObjectRequest.setStorageClass(StorageClass.Standard);

        try {
            PutObjectResult putObjectResult = cosclient.putObject(putObjectRequest);
            // putobjectResult会返回文件的etag
            String etag = putObjectResult.getETag();
        } catch (Exception e) {
            throw new DataException(RespConsts.SERVICE_ERROR, "腾讯cos上传文件接口调用错误", e);
        }

        return key;

    }


}
